//
// Created by shaun on 5/21/2025.
//

#include "generic_controller.h"
#include "sdk_logging_api.h"
#include "sdk_command_api.h"
#include "sdk_command_facade.h"
#include "props.h"

namespace eintik::presentation::controller
{
    GenericController::GenericController()
    {
        ConfigEnableAutoUpdateAsync();
        ConfigEnableDirectSaveAsync();
    }

    void GenericController::OnStartClicked()
    {
        LOG_INFO("AscanViewController::OnStartClicked");

        DeviceStartAsync([](const bool success)
        {
            LOG_INFO("Async, Device started {}", success ? "successfully." : "failed.");
        });

        DeviceEncoderResetAsync(0,[](const bool success){
            LOG_INFO("Async, Device started {}", success ? "successfully." : "failed.");
        });

        StorageStartAsync();
    }

    void GenericController::OnStopClicked()
    {
        LOG_INFO("AscanViewController::OnStopClicked");

        DeviceStopAsync([](const bool success)
        {
            LOG_INFO("Async, Device stopped {}", success ? "successfully." : "failed.");
        });
        StorageStopAsync();
    }

    void GenericController::OnDebugClicked()
    {
        LOG_INFO("AscanViewController::OnDebugClicked");

        DebugAsync([](const bool success)
        {
            LOG_INFO("Async, Debug command executed {}", success ? "successfully." : "failed.");
        });
    }

    void GenericController::OnConnectClicked()
    {
        LOG_INFO("AscanViewController::OnConnectClicked");

        NetworkConnectAsync([](const bool success)
        {
            LOG_INFO("Async, Network connected {}", success ? "successfully." : "failed.");
        });
    }

    void GenericController::OnCloseClicked()
    {
        LOG_INFO("AscanViewController::OnCloseClicked");

        NetworkDisconnectAsync([](const bool success)
        {
            LOG_INFO("Async, Network disconnected {}", success ? "successfully." : "failed.");
        });
    }

    void GenericController::OnSetClicked()
    {
        LOG_INFO("AscanViewController::OnSetClicked");

        DeviceSetAsync([](const bool success)
        {
            LOG_INFO("Async, Device synced {}", success ? "successfully." : "failed.");
        });
    }

    void GenericController::OnConfigClicked()
    {
        std::unordered_map<KeyType, ValueType> params;
        emit GetParameters(params);
        OnParameterChanged(params);
    }

    void GenericController::OnParameterChanged(const std::unordered_map<KeyType, ValueType>& params)
    {
        LOG_INFO("AscanViewController::OnParameterChanged");

        // group0 global parameters
        std::unordered_map<KeyType, ValueType> global_params;

        facade::ConfigGroupBuilder builder;
        builder.Clear();

        // (1) Collect global params
        const auto global_group = std::make_shared<facade::GlobalConfigGroup>();

        global_group->SetPaVoltage(std::get<int>(params.at(kPaVoltage)));
        global_group->SetFrameRate(std::get<int>(params.at(kFrameRate)));
        global_group->SetTriggerCapture(TriggerCaptureType::kContinuous);

        builder.Append(global_group);

        // (2) Collect PA params
        const auto pa_group = std::make_shared<facade::PhaseArrayConfigGroup>(1);
        pa_group->SetEnable(true);
        pa_group->SetGainDb(std::get<double>(params.at(kGainDb)));
        
        using namespace eintik::property;
        auto wave_speed = std::get<int>(params.at(kWaveSpeed));
        auto scan_start = std::get<double>(params.at(kScanStartUs));
        auto scan_range = std::get<double>(params.at(kScanRangeUs));
        auto scan_end = scan_start + scan_range;
        auto bc = on_point(scan_start, scan_end, wave_speed, std::get<int>(params.at(kSampleQty)));
        pa_group->SetScanStartUs(delay_time(scan_start));
        pa_group->SetScanRangeUs(bc.second);
        pa_group->SetSampleQty(bc.first);
        pa_group->SetPulseWidthNs(std::get<int>(params.at(kPulseWidthNs)));

        pa_group->SetFocalLawType(FocalLawType::kUltrasonicMicroscopy);
        pa_group->SetFocalLawId(0);
        pa_group->SetFocalLawEnable(true);

        pa_group->SetFocalLawKV(kStartElement, std::get<int>(params.at(kStartElement)) - 1);
        pa_group->SetFocalLawKV(kEndElement, std::get<int>(params.at(kEndElement)));
        pa_group->SetFocalLawKV(kAperture, std::get<int>(params.at(kAperture)));
        pa_group->SetFocalLawKV(kStep, std::get<int>(params.at(kStep)));

        builder.Append(pa_group);

        const auto storage_group = std::make_shared<facade::StorageConfigGroup>();

        auto type = property::start_type();
        if ( type == 2) {
            storage_group->SetStartType(RecoderStartType::kDelayTime);
            storage_group->SetStartValue(property::encoder_delay());
            LOG_INFO("kDelayTime触发");
        }else if (type == 3) {
            storage_group->SetStartType(RecoderStartType::kEncoderDistance);
            storage_group->SetStartValue(property::encoder_delay());
            LOG_INFO("kEncoderDistance触发");
        }

#if 0
        storage_group->SetStartType(RecoderStartType::kDelayTime);
        // storage_group->SetStartValue(property::encoder_delay());
        storage_group->SetStartValue(1000);
#endif

        builder.Append(storage_group);
        builder.CommitAsync();
    }

} // namespace modules::user_interface::ascan
